package com.scs.application.modules.dept.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.consts.SerialKeys;
import com.scs.application.core.consts.ErrorCode;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UserUtils;
import com.scs.application.modules.base.entity.Dept;
import com.scs.application.modules.base.entity.DeptMap;
import com.scs.application.modules.base.entity.Matr;
import com.scs.application.modules.base.service.DeptMapService;
import com.scs.application.modules.base.service.DeptService;
import com.scs.application.modules.base.service.MatrService;
import com.scs.application.modules.base.service.UserWarehouseService;
import com.scs.application.modules.base.util.SingleService;
import com.scs.application.modules.base.vo.UserWarehouseVO;
import com.scs.application.modules.dept.entity.HisBill;
import com.scs.application.modules.dept.entity.UseBill;
import com.scs.application.modules.dept.mapper.HisBillMapper;
import com.scs.application.modules.dept.service.HisBillService;
import com.scs.application.modules.dept.service.UseBillService;
import com.scs.application.modules.report.handler.BeforeReport;
import com.scs.application.modules.sys.entity.Log;
import com.scs.application.modules.sys.enums.BusType;
import com.scs.application.modules.sys.enums.LogType;
import com.scs.application.modules.sys.model.RestResult;
import com.scs.application.modules.thirdparty.dto.HisOprtUse;
import com.scs.application.modules.wm.entity.Stock;
import com.scs.application.modules.wm.entity.Transfer;
import com.scs.application.modules.wm.service.StockService;
import com.scs.application.modules.wm.service.TransferItemService;
import com.scs.application.modules.wm.service.TransferService;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class HisBillServiceImpl extends BaseServiceImpl<HisBillMapper, HisBill> implements HisBillService {

    @Autowired
    private StockService stockService;
    @Autowired
    private DeptService deptService;
    @Autowired
    private DeptMapService deptMapService;
    @Autowired
    private UseBillService useBillService;
    @Autowired
    private TransferService transferService;
    @Autowired
    private TransferItemService transferItemService;
    @Autowired
    private MatrService matrService;
    @Autowired
    private UserWarehouseService userWarehouseService;
    @Override
    public Page<?> page(QueryContext context) {
        BeforeReport beforeReport=new BeforeReport();
        QueryWrapper wrapper = new QueryWrapper() ;
        List<String> hrpIds = new ArrayList<>();
        List<String> hisIds = new ArrayList<>();
        if (!beforeReport.getFlagAllData()) {
            //登录用户可用工位
            List<UserWarehouseVO> userWarehouseList = userWarehouseService.getUserWarehouse();
//        if(userWarehouseList == null || userWarehouseList.size() <1)   return null;
            //判断该仓库科室下是否包含该人员的科室
            if (!userWarehouseList.stream().filter(w->String.valueOf(w.getDeptId()).equals(UserUtils.currentUser().getDeptId())).findAny().isPresent()){
                UserWarehouseVO us=new UserWarehouseVO();
                us.setDeptId(UserUtils.currentUser().getDeptId());
                userWarehouseList.add(us);
            }
            List<String> ids = new ArrayList<>();
            userWarehouseList.forEach(userWarehouse -> {
                if (StringUtils.isNotBlank(userWarehouse.getDeptId())) {
                    ids.add(userWarehouse.getDeptId());
                }
            });
            List<Dept> depts=deptService.list(Wrappers.<Dept>query().in("id",ids));
            hrpIds=depts.stream().map(Dept::getHrpCode).collect(Collectors.toList());
            List<DeptMap> deptMaps=deptMapService.list(Wrappers.<DeptMap>query().in("hrp_code",hrpIds));
            hisIds=deptMaps.stream().map(DeptMap::getHisCode).collect(Collectors.toList());
            List<String> hisList=hisIds.stream().distinct().collect(Collectors.toList());
            context.getParams().put("deptIdList",String.join(",", hisList));
        }
        return super.page(context);
    }

    @Override
    public RestResult scanUseSN(String matrCodeHis, String inpatientCode, String sn, String opType, String hisKey,String outpatientNo, String oprtNo) {
        JSONObject logdesc = new JSONObject();
        Log log = Log.getLog(BusType.HisType.type07, LogType.success, "system", logdesc);
        RestResult result=RestResult.ok("后补扫码消耗成功！！");
        result.setMsg("扫码消耗成功！！");
        //校验此消耗是否已经绑码消耗成功
//        UseBill useBill=useBillService.getOne(Wrappers.<UseBill>query().eq("his_key",hisKey));
//        if(useBill !=null){
//            throw new BusinessException("该收费项目名称:【%s】,编码:【%s】已经绑定sn【%s】消耗，请重新选择收费明细项目进行扫码消耗！", useBill.getMatrNameHis(),matrCodeHis,useBill.getSn());
//        }

        HisOprtUse hisOprtUse = new HisOprtUse();
        try{
            //校验库存记录
            //校验库存
            Stock stock= stockService.getOne(Wrappers.<Stock>query().in("sn", sn).or().in("rfid", sn));
            Matr matr= matrService.getOne(Wrappers.<Matr>query().eq("id",stock.getMatrId()));
            if(!matr.getHrpCode().equals(matrCodeHis)){
                throw new BusinessException("该收费编码【%s】与库存耗材编码【%s】不一致，不能扫码消耗，请检查！", matrCodeHis,matr.getHrpCode());
            }
            if(stock==null)
            {
                throw new BusinessException("该唯一码【%s】未找到相关库存记录，不能扫码消耗，请检查！", sn);
            }
            //校验开单科室是不是库存地科室
            //获取收费项目记录
            HisBill hisBill=new HisBill();
            if(inpatientCode!=null && !inpatientCode.equals("null") && !inpatientCode.equals("") ){
                hisBill=this.getOne(Wrappers.<HisBill>query().eq("matr_code_his",matrCodeHis).eq("inpatient_no",inpatientCode).eq("his_key",hisKey));
            }else if(outpatientNo!=null && !outpatientNo.equals("null") && !outpatientNo.equals("")){
                hisBill=this.getOne(Wrappers.<HisBill>query().eq("matr_code_his",matrCodeHis).eq("outpatient_no",outpatientNo).eq("his_key",hisKey));
            }else{
                hisBill=this.getOne(Wrappers.<HisBill>query().eq("matr_code_his",matrCodeHis).eq("oprt_code",oprtNo).eq("his_key",hisKey));
            }

            if(hisBill==null) throw new BusinessException("未找到对应收费明细记录，不能扫码消耗，请检查！");
            if(StringUtils.isBlank(hisBill.getRefKey())) throw new BusinessException("对应收费明细没有ref_key记录，不能扫码消耗，请检查！");
            if(hisBill.getBillFlag() == null || hisBill.getBillFlag() != 1) throw new BusinessException("对应收费明细不是计费记录，不能扫码消耗，请检查！");
            //获取该开单科室科室对应的hrp科室
            DeptMap deptMap=deptMapService.getOne(Wrappers.<DeptMap>query().eq("his_code", hisBill.getDeptCodeOp()));
            if(deptMap==null){
                throw new BusinessException("未找到开单科室【%s】对应HRP科室，不能扫码消耗，请维护科室关系之后进行消耗！",hisBill.getDeptNameOp());
            }
            //获取该执行科室科室对应的hrp科室
            DeptMap deptMap1=deptMapService.getOne(Wrappers.<DeptMap>query().eq("his_code", hisBill.getDeptCodePatient()));
            if(deptMap1==null){
                throw new BusinessException("未找到执行科室【%s】对应HRP科室，不能扫码消耗，请维护科室关系之后进行消耗！",hisBill.getDeptNamePatient());
            }
            // 获取该科室的仓库id
            Dept dept= deptService.getOne(Wrappers.<Dept>query().eq("hrp_code",deptMap.getHrpCode()));
            //如果该科室仓库和库存地仓库不一致则生成调拨单，由原有库存仓库调入开单科室所在仓库
            if(dept.getWarehouseId()!=stock.getWarehouseId()){
                //生成调拨单
                Date dateNow=new Date();
                LocalDateTime localDateTime = LocalDateTime.now();
                //1、创建调拨单
                Transfer transfer=new Transfer();
                transfer.setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.WM_TRANSFER_BUS_KEY))
                        .setBusDate(dateNow)
                        .setBusUser(UserUtils.currentUser().getCode()).setBusUserCode(UserUtils.currentUser().getWorkNo())

                        //调入库存地为 库存所在仓库
                        .setFromWarehouseId(stock.getWarehouseId()).setFromWarehouseName(stock.getWarehouseName())

                        //调出仓库为操作智能柜
                        .setToWarehouseId(dept.getWarehouseId()).setToWarehouseName(dept.getWarehouseName())
                        .setDeptIdTo(dept.getId())
                        .setDeptNameTo(dept.getName())
                        .setRemark("")
                        //流程状态
                        .setFlowStatus(GlobalConsts.FLOW_END_VALUE)
                        .setFlowModifier(UserUtils.currentUser().getCode()).setFlowModified(localDateTime);
                transferService.save(transfer);

                //2、添加调拨单明细并锁定库存
                List<String> sns = Lists.newArrayListWithCapacity(1);
                sns.add(sn);
                transferItemService.addTransferItems(transfer.getId(), sns, null);
                //生成出入库单
                transferService.autoOutIn(transfer,true);

            }
            //计费流程
            ;
            hisOprtUse.setBillFlag(1)
                    .setRefkey(hisBill.getRefKey())
                    .setBusDate(DateUtils.parse(DateUtils.format(hisBill.getBillDate(),"yyyy-MM-dd HH:mm:ss")))
                    .setDeptCodeUse(deptMap.getHisCode())
                    .setDeptCodeExec(deptMap1.getHisCode())
                    .setOprtCode(hisBill.getOprtCode())
                    .setUser(hisBill.getExecUser())
                    .setInpatientNo(hisBill.getInpatientNo())
                    .setOutpatientNo(hisBill.getOutpatientNo())
            ;
            HisOprtUse.HisOprtUserDtl dtl=new HisOprtUse.HisOprtUserDtl();
            List<HisOprtUse.HisOprtUserDtl> dtls=new ArrayList<HisOprtUse.HisOprtUserDtl>();
            dtl.setHisCode(hisBill.getMatrCodeHis()).setUniqueCode(sn);
            dtls.add(dtl);
            hisOprtUse.setDtls(dtls);
            hisOprtUse.setType("hisBack");
            hisOprtUse.setPatientName(hisBill.getPatientName());
            ;
            result.setData(SingleService.inst.oprtUseService.hisSaveOprtUse(hisOprtUse));

            UseBill useBill1=new UseBill();
            BeanUtils.copyProperties(hisBill, useBill1);
            //保存更新记录
            useBill1.setSn(sn).setHisBillId(hisBill.getId());
            useBill1.setId("");
            useBillService.save(useBill1);
            //获取扫码数量
            int count= useBillService.count(Wrappers.<UseBill>query().eq("his_key",hisBill.getHisKey()));
            hisBill.setScanQty(count);
            this.updateById(hisBill);
        }catch (Exception e){
            result.setCode(ErrorCode.COMMON_ERROR);
            result.setMsg("操作失败," + e.getMessage());
            result.setSuccess(false);
            log.setLog(LogType.error, e.getMessage());
            logger.error(e.getMessage());
        }
        return result;
    }



}
